/******************************************************************************
 * @file system_adaptor.c
 *
 * @par dependencies
 *  - system_adaptor.h
 *
 * @brief Implements the LED handler module, providing high-level interfaces
 *        for managing and controlling LED hardware operations.
 *
 * Processing flow:
 *
 * call directly.
 *
 * @author iceiceiceberg
 *
 * @date 2025-05-11
 *
 * @version V1.0.0
 *
 * @note 1 tab == 4 spaces
 *
 *****************************************************************************/

 //********************************* Includes ********************************//
#include "system_adaptor.h"

//********************************* Includes ********************************//

//********************************* Defines *********************************//
#define UNIT_DEBUG

#ifndef SYSTEM_QUICK_BOOT

bsp_led_handler_t handler1 = {0};
bsp_led_driver_t led1 = {0};
bsp_led_driver_t led2 = {0};

#else

__attribute__((used,section("bsp_target")))
bsp_led_handler_t handler1 = { 
    .is_instantiated = LED_IS_INSTED,
    .led_instance = { 
        .array_led_driver = { &led1, &led2 },
        .index = LED3
    },
    .p_os_critical    = &handler1_os_critical,
    .p_os_delay       = &handler1_os_delay,
    .p_os_queue       = &handler1_os_queue,
    .p_os_thread      = &handler1_os_thread,
    .p_queue_handle   = NULL,
    .p_thread_handle  = NULL,
    .p_sys_time_base  = &handler1_get_core_base_time,
    .pf_led_controler = led_control,
    .pf_led_register  = led_register
};

__attribute__((used,section("bsp_target")))
bsp_led_driver_t led1 = { 
    .is_instantiated = LED_IS_INSTED,
    .cycle_period_ms = 0,
    .blink_times     = 0,
    .blink_proportion_on_off = PROPORTION_ON_OFF_X_X,
    .p_led_ops_instance = &my_led_ops_instance
 };

__attribute__((used,section("bsp_target")))
bsp_led_driver_t led2 = { 
    .is_instantiated = LED_IS_INSTED,
    .cycle_period_ms = 0,
    .blink_times     = 0,
    .blink_proportion_on_off = PROPORTION_ON_OFF_X_X,
    .p_led_ops_instance = &my_led_ops_instance
 };

#endif // SYSTEM_QUICK_BOOT

led_state_t my_led_on  ( void )
{
    DEBUG_PRINT( "LED ON\r\n" );

    return LED_OK;
}

led_state_t my_led_off ( void )
{
    DEBUG_PRINT( "LED OFF\r\n" );

    return LED_OK;
}

led_opes_t my_led_ops_instance = {
    .pf_led_on  = my_led_on,
    .pf_led_off = my_led_off
};

handler_state_t handler_get_core_base_time ( uint32_t * const p_time )
{
    if( NULL == p_time )
    {
        return HANDLER_ERROR_PARAM;
    }

    *p_time = HAL_GetTick(); 
#ifdef UNIT_DEBUG
    DEBUG_PRINT( "Handler get core base time: %d\r\n", *p_time );
#endif // UNIT_DEBUG

    return HANDLER_OK;
}

handler_core_base_time_ms_t handler1_get_core_base_time = {
    .pf_handler_get_core_base_time = handler_get_core_base_time
};

handler_state_t handler_os_delay( uint32_t const delay_time )
{
    //vTaskDelay( delay_time );
    osDelay( delay_time );
#ifdef UNIT_DEBUG
    DEBUG_PRINT( "Handler OS delay: %d\r\n", delay_time );
#endif // UNIT_DEBUG

    return HANDLER_OK;
}

handler_os_delay_t handler1_os_delay = {
    .pf_handler_os_delay = handler_os_delay
};

handler_state_t handler1_os_queue_create( uint32_t const      iterm_num,
                                          uint32_t const     iterm_size,
                                          void **  const p_queue_handle)
{
    QueueHandle_t temp_queue_handle = NULL;

    temp_queue_handle = xQueueCreate( iterm_num, iterm_size );
    if( NULL == temp_queue_handle )
    {
        return HANDLER_ERROR_RESOURCE;
    }
    else
    {
        *p_queue_handle = temp_queue_handle;
    }

#ifdef UNIT_DEBUG
    //DEBUG_PRINT( "queue created with handle: %p\r\n", *p_queue_handle );
#endif // UNIT_DEBUG

    return HANDLER_OK;
}

handler_state_t handler1_os_queue_put (void *   const  p_queue_handle,
                                       void *   const          p_item,
                                       uint32_t const         timeout)
{
#ifdef UNIT_DEBUG
    DEBUG_PRINT( "os_queue_put_handler1\r\n" );
#endif // UNIT_DEBUG

    if( NULL == p_queue_handle || 
        NULL == p_item         ||
        timeout >= portMAX_DELAY
                                 )
    {
        return HANDLER_ERROR_PARAM;
    }
    else
    {
        BaseType_t ret = xQueueSend( p_queue_handle, p_item, timeout );
        if( pdFALSE == ret )
        {
            return HANDLER_ERROR;
        }

        return HANDLER_OK;
    }
}

handler_state_t handler1_os_queue_get (void *   const  p_queue_handle,
                                       void *   const             msg,
                                       uint32_t const         timeout)
{
#ifdef UNIT_DEBUG
    DEBUG_PRINT( "os_queue_get_handler1\r\n" );
#endif // UNIT_DEBUG

    if( NULL == p_queue_handle || 
        NULL == msg            ||
        timeout >= portMAX_DELAY
                                 )
    {
        return HANDLER_ERROR_PARAM;
    }
    else
    {
        BaseType_t ret = xQueueReceive( p_queue_handle, msg, timeout );
        if( pdPASS == ret )
        {
            return HANDLER_OK;
        }

        return HANDLER_ERROR;
    }
}

handler_state_t handler1_os_queue_delete( void *   const  p_queue_handle )
{
#ifdef UNIT_DEBUG
    DEBUG_PRINT("os_queue_delete_handler1\r\n");
#endif // UNIT_DEBUG

    if( NULL == p_queue_handle )
    {
        return HANDLER_ERROR_PARAM;
    }

    vQueueDelete( p_queue_handle );
    return HANDLER_OK;
}

handler_os_queue_t handler1_os_queue = {
    .pf_os_queue_create = handler1_os_queue_create,
    .pf_os_queue_put    = handler1_os_queue_put,
    .pf_os_queue_get    = handler1_os_queue_get,
    .pf_os_queue_delete = handler1_os_queue_delete
};

 handler_state_t os_thread_create_handler1 (
                                          void *           p_task_function,
							        const char *   const            p_name,		
							        const uint16_t            usStackDepth,
							              void *   const   p_thread_params,
							              uint32_t         thread_priority,
							              void **  const p_thread_handler )
{
    BaseType_t ret = pdPASS;

#ifdef UNIT_DEBUG
    DEBUG_PRINT( "os_thread_create_handler1\r\n" );
#endif // UNIT_DEBUG

    if ( NULL == p_task_function || 
         NULL == p_name          || 
         NULL == p_thread_handler  )
    {
#ifdef UNIT_DEBUG  
        DEBUG_PRINT( "os_thread_create_handler1: HANDLER_ERROR_PARAM\r\n" );
#endif // UNIT_DEBUG

        return HANDLER_ERROR_PARAM;
    }

    // Create the thread
    ret = xTaskCreate ( ( TaskFunction_t ) p_task_function, 
                                           "led_handler_1", 
                                               ( 128 * 4 ), 
                                           p_thread_params, 
                                          osPriorityNormal, 
                      ( TaskHandle_t * ) p_thread_handler );
    
    if ( pdPASS != ret )
    {
#ifdef UNIT_DEBUG
        DEBUG_PRINT( "os_thread_create_handler1: HANDLER_ERROR_RESOURCE\r\n" );
#endif // UNIT_DEBUG
        return HANDLER_ERROR_RESOURCE;
    }

    return HANDLER_OK;
}

handler_state_t os_thread_delete_handler1 ( void * const p_thread_handler )
{
    handler_state_t ret = HANDLER_OK;

    if ( NULL == p_thread_handler )
    {
#ifdef UNIT_DEBUG
        DEBUG_PRINT( "os_thread_delete_handler1: HANDLER_ERROR_PARAM\r\n" );
#endif // UNIT_DEBUG

        return HANDLER_ERROR_PARAM;
    }

    vTaskDelete( ( TaskHandle_t ) p_thread_handler );
    
    return ret;
}

handler_os_thread_t handler1_os_thread = {
    .pf_os_thread_create = os_thread_create_handler1,
    .pf_os_thread_delete = os_thread_delete_handler1
};

handler_state_t handler1_os_critical_enter( void )
{
#ifdef UNIT_DEBUG
    DEBUG_PRINT( "os_critical_enter_handler1\r\n" ) ;
#endif // UNIT_DEBUG

    // Enter critical section
    taskENTER_CRITICAL();

    return HANDLER_OK;
}

handler_state_t handler1_os_critical_exit( void )
{
#ifdef UNIT_DEBUG
    DEBUG_PRINT ( "os_critical_exit_handler1\r\n" ) ;
#endif // UNIT_DEBUG

    // Exit critical section
    taskEXIT_CRITICAL ();

    return HANDLER_OK;
}

handler_os_critical_t handler1_os_critical = {
    .pf_handler_os_critical_enter = handler1_os_critical_enter,
    .pf_handler_os_critical_exit  = handler1_os_critical_exit
};

void test2( void )
{
#ifndef SYSTEM_QUICK_BOOT
//********************************* Driver *******************************//
    led_state_t ret_driver = LED_OK;

    ret_driver = bsp_led_driver_inst(
        &led1,
        &my_led_ops_instance
    );

    ret_driver = bsp_led_driver_inst(
        &led2,
        &my_led_ops_instance
    );

    if (LED_OK != ret_driver )
    {
        printf( "LED driver instantiation failed with error: %d\r\n", 
                                                         ret_driver );
    }
    else
    {
        printf( "LED blinking started.\n\r" );
    }

//********************************* Handler *******************************//
    handler_state_t ret = HANDLER_OK;

    ret = bsp_led_handler_inst(
                          &handler1,
                          &handler1_get_core_base_time,
                          &handler1_os_delay,
                          &handler1_os_queue,
                          &handler1_os_thread,
                          &handler1_os_critical
                          );

    if( HANDLER_OK == ret )
    {

    }

//********************************* Intergrate ******************************//
    index_led_instance_t led1_handler1_idx = LED_NOT_INISTED;
    index_led_instance_t led2_handler1_idx = LED_NOT_INISTED;

    handler1.pf_led_register ( &handler1,
                                   &led1,
                      &led1_handler1_idx );

#ifdef UNIT_DEBUG
    DEBUG_PRINT( "LED1 handler index: %d\r\n", led1_handler1_idx );
#endif // UNIT_DEBUG

    handler1.pf_led_register ( &handler1,
                                   &led2,
                      &led2_handler1_idx );

#ifdef UNIT_DEBUG
    DEBUG_PRINT( "LED2 handler index: %d\r\n", led2_handler1_idx );
#endif // UNIT_DEBUG

#ifdef UNIT_DEBUG
    DEBUG_PRINT( "handler1 index: %d\r\n", handler1.led_instance.index );
#endif // UNIT_DEBUG

//********************************* APP *************************************//
#else
    index_led_instance_t led1_handler1_idx = LED1;
    index_led_instance_t led2_handler1_idx = LED2;
    
    bsp_led_handler_inst_os_resrc_for_quick_boot ( &handler1 );

#endif // SYSTEM_QUICK_BOOT

    handler1.pf_led_controler ( &handler1,
                                        4,
                                        2,
                    PROPORTION_ON_OFF_1_1,
                      led1_handler1_idx );

    handler1.pf_led_controler ( &handler1,
                                        4,
                                        1,
                    PROPORTION_ON_OFF_1_3,
                      led2_handler1_idx );

}

//********************************* Defines *********************************//

//********************************* Declaring *******************************//

//********************************* Declaring *******************************//
